package com.wjk.kylin.rpc.core.serialize;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONReader;
import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import com.wjk.kylin.rpc.core.util.RpcException;

import java.io.*;

/**
 * 序列化工具
 * 支持json、jdk、Hessian
 * @author wjk
 */
public interface Serializer {

    /**
     * 序列化
     *
     * @param object
     * @param <T>
     * @return
     */
    <T> byte[] serialize(T object);

    /**
     * 反序列化
     *
     * @param bytes
     * @param clazz
     * @param <T>
     * @return
     */
    <T> Object deserialize(byte[] bytes, Class<T> clazz);

    /**
     * 序列化
     */
    enum Algorithm implements Serializer {
        /**
         * java 序列化
         */
        Java {
            @Override
            public <T> Object deserialize(byte[] bytes, Class<T> clazz) {
                try {
                    ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
                    return (T) ois.readObject();
                } catch (IOException | ClassNotFoundException e) {
                    throw new RuntimeException("反序列化失败", e);
                }
            }

            @Override
            public <T> byte[] serialize(T object) {
                try {
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    ObjectOutputStream oos = new ObjectOutputStream(bos);
                    oos.writeObject(object);
                    return bos.toByteArray();
                } catch (IOException e) {
                    throw new RuntimeException("序列化失败", e);
                }
            }
        },

        /**
         * TODO 会出现long转为double问题
         */
      /*  Gson {
            @Override
            public <T> Object deserialize(byte[] bytes, Class<T> clazz) {
                Gson gson = new GsonBuilder().registerTypeAdapter(Class.class, new ClassCodec()).create();
                String json = new String(bytes, StandardCharsets.UTF_8);
                return gson.fromJson(json, clazz);
            }

            @Override
            public <T> byte[] serialize(T object) {
                Gson gson = new GsonBuilder().registerTypeAdapter(Class.class, new ClassCodec()).create();
                String json = gson.toJson(object);
                return json.getBytes(StandardCharsets.UTF_8);
            }
        },*/
        /**
         * json序列化
         */
        FastJson {
            @Override
            public <T> Object deserialize(byte[] bytes, Class<T> clazz) {
                return JSON.parseObject(bytes, clazz, JSONReader.Feature.SupportClassForName);
            }

            @Override
            public <T> byte[] serialize(T object) {
                return JSON.toJSONBytes(object);
            }
        },
        /**
         * hessian 序列化
         */
        Hessian {
            @Override
            public <T> Object deserialize(byte[] bytes, Class<T> clazz) {
                ByteArrayInputStream is = new ByteArrayInputStream(bytes);
                Hessian2Input hi = new Hessian2Input(is);
                try {
                    Object result = hi.readObject();
                    return result;
                } catch (IOException e) {
                    throw new RpcException(e);
                } finally {
                    try {
                        hi.close();
                    } catch (Exception e) {
                        throw new RpcException(e);
                    }
                    try {
                        is.close();
                    } catch (IOException e) {
                        throw new RpcException(e);
                    }
                }
            }

            @Override
            public <T> byte[] serialize(T object) {
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                Hessian2Output ho = new Hessian2Output(os);
                try {
                    ho.writeObject(object);
                    ho.flush();
                    byte[] result = os.toByteArray();
                    return result;
                } catch (IOException e) {
                    throw new RpcException(e);
                } finally {
                    try {
                        ho.close();
                    } catch (IOException e) {
                        throw new RpcException(e);
                    }
                    try {
                        os.close();
                    } catch (IOException e) {
                        throw new RpcException(e);
                    }
                }
            }
        }
    }

   /* class ClassCodec implements JsonSerializer<Class<?>>, JsonDeserializer<Class<?>> {

        @Override
        public Class<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            try {
                String str = json.getAsString();
                return Class.forName(str);
            } catch (ClassNotFoundException e) {
                throw new RpcException(e);
            }
        }

        @Override
        public JsonElement serialize(Class<?> src, Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(src.getName());
        }
    }*/
}
